package main

/*
	echoserver
		---> working at port of 8080
	echoserver 10000
		---> working at port of 10000
*/

import (
	"fmt"
	"io"
	"log"
	"net"
	"os"
)

const helpString = `
（以下使用 EXE 指代可执行文件名）

获取帮助信息: 
- EXE
- EXE -h | --help | help

如何使用：
第一个参数为服务地址(如 0.0.0.0:10250)，第二个参数为转发地址(如 127.0.0.1:10255)
例如：
EXE 0.0.0.0:10250 127.0.0.1:10255
`

func main() {
	// Attention: Args[0] is this exe-file name/path
	argNum := len(os.Args) - 1

	if argNum == 0 || (argNum >= 1 && (os.Args[1] == "-h" || os.Args[1] == "--help" || os.Args[1] == "help")) {
		fmt.Println(helpString)
	}
	if argNum != 2 {
		println(helpString)
		//log.Fatal(helpString)
		return
	} else {
		fromAddr := os.Args[1]
		toAddr := os.Args[2]
		tcpForward(fromAddr, toAddr)
	}
}

func tcpForward(fromAddr string, toAddr string) {
	listener, err := net.Listen("tcp", fromAddr)
	if err != nil {
		log.Println(err)
		return
	}
	fmt.Println("----------------------------------------------")
	log.Printf("TCP转发：%v ====> %v\n", fromAddr, toAddr)
	fmt.Println("----------------------------------------------")
	defer listener.Close()
	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Printf("建立连接错误:%v\n", err)
			continue
		}
		log.Printf("remote:%v ----> local:%v\n", conn.RemoteAddr(), conn.LocalAddr())
		go handle(conn, toAddr)
	}
}

func handle(fromConn net.Conn, toAddr string) {
	defer fromConn.Close()
	toConn, err := net.Dial("tcp", toAddr)
	if err != nil {
		log.Printf("连接%v失败:%v\n", toAddr, err)
		return
	}
	ExitChan := make(chan bool, 1)
	go func(fromConn net.Conn, toConn net.Conn, Exit chan bool) {
		_, err := io.Copy(toConn, fromConn)
		if err != nil {
			log.Printf("往%v发送数据失败:%v\n", toAddr, err)
		}
		ExitChan <- true
	}(fromConn, toConn, ExitChan)
	go func(fromConn net.Conn, toConn net.Conn, Exit chan bool) {
		_, err := io.Copy(fromConn, toConn)
		if err != nil {
			log.Printf("从%v接收数据失败:%v\n", toAddr, err)
		}
		ExitChan <- true
	}(fromConn, toConn, ExitChan)
	<-ExitChan
	toConn.Close()
}
